#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"

# Variables

# Type de fichiers à filtrer
set file_types ""    
listbox .listePipeLecture

#Procedure de mise à jour du nom du chemin courant d'une fenetre d'exploration
proc set_label_chemin { nom_chemin label } {
	$label configure -text "Fichier courant : $nom_chemin"
}

# met à jour la liste des types de fichiers à filtrer
proc set_file_types {} {
    global file_types
    set file_types {
    	{"Fichiers Pascal" { .p .P} }
        {"Fichiers Lex" { .l .L} }
        {"Fichiers TCL/TK" { .tcl .TCL .tk .TK} }
        {"Fichiers texte" { .txt .TXT} }
        {"All Files" * }
    }
}

# Procédure d'écriture dans un fichier texte
proc ecriture_fichier {filename data} {
    # Ouverture du fichier
    set fileid [open $filename w]
    # écriture des données du widget text dans le fichier ouvert en lecture 
    puts -nonewline $fileid $data 
    # Fermeture du fichier
    close $fileid
}

#procedure de fermeture de l'interface graphique
proc fermer_interface {} {
    exit
}

#procedure qui permet de selectionner un fichier et d'afficher son contenu dans la fenetre compilation
proc nouveau_fichier {} {
    .txt_compilation delete 1.0 end
}

#Procédure appelée lors du clic sur le bouton "Ouvrir"
proc ouvrir_fichier {} {
    #Creation des types de fichiers
    set_file_types
    global filename #récupération du chemin du fichier
    global file_types
    
    set data [.txt_compilation get 1.0 {end -1c}] 

        #nouveau nom de fichier
    set new_filename [tk_getOpenFile -filetypes $file_types\
       -initialdir [file dirname $filename] \
       -initialfile [file tail $filename] \
       -defaultextension .tcl]
    if {$new_filename == ""} {
       # The user pressed "cancel"
       return
    }
    
    ouvrir_fichier_et_afficher .txt_compilation .lbl_titre_compilation $new_filename nbLignesPascal .lst_lignes_Pascal
    
    set filename $new_filename
}

# Procédure d'enregistrement du fichier courant
proc enregistrer_fichier { } {
    # Récupération du chemin du fichier
    global filename
    # Données de texte
    set data [.txt_compilation get 1.0 {end -1c}] 
    if {$data == ""} {
               # Affichage d'un message d'erreur dans le cas où le nom du fichier est incorrect
       	tk_messageBox -title "Erreur compilation " -icon error -message "Impossible d'enregistrer."
            # The user pressed "cancel"
            return
    }
    # Ecriture dans le fichier
    ecriture_fichier $filename $data
 }

# Enregistre le fichier sous
proc enregistrer_sous { } {

	#Creation des types de fichiers
    set_file_types
    global filename
    global file_types
    set data [.txt_compilation get 1.0 {end -1c}]
    set filename [tk_getSaveFile -filetypes $file_types\
        -initialdir pwd -initialfile $filename\
        -defaultextension .tcl]
        
    if {$filename == ""} {
            return
    }
    # Mise a jour du nom du fichier ouvert
    set_label_chemin $filename .lbl_titre_compilation
    # Ecriture dans le fichier
    ecriture_fichier $filename $data
}

#appelée au moment de l'appui sur le bouton Entrée, dans la console de saisie
proc getLineConsole {} {
	global pipe_my_loop fichier_ecriture fichier_lecture texteLu
        
    #Récupération du contenu de la console de saisi et positionnement du marqueur au début, après effacement
    set text [.console_saisi get "end - 1 lines" "end - 1 char"]
    .console_saisi delete 1.0 end
    .console_saisi mark set insert "1.0 -1 char"
    
    puts $pipe_my_loop  "inpu:$text\n"
    
    #ecriture_fichier $fichier_ecriture "stac:int var$3$bool b$true$double pi$3.14$\n"

	#ecriture_fichier $fichier_ecriture "$text\n"
    #gets $pipeFichierLecture texteLu

    traitementMessages
}


proc ecriture_console {} {
	global pipeFichierLecture
    #attente de 100 millisecondes
    after 100
    gets $pipeFichierLecture line
    #Remplacement des caractère éronnées par un caractère vide
    set chaine [string map {\x00 ""} $line]

    # Insertion du contenu du fichier
    .console insert end "$chaine\n"
    #Positionnement du curseur à la fin de la console d'affichage
    .console see end
}

#Permet de traiter les messages lancés par l'intrepreteur de PCod, selon le protocole applicatif
proc traitementMessages {} {
    global pipeFichierLecture texteLu
    #attente de 100 millisecondes
    after 100
    #Remplacement des caractère éronnées par un caractère vide
    set chaine [string map {\x00 ""} $texteLu]

	#Extraction du type de message à traiter
    set msg [regexp -inline -all -- {.*\:} $chaine]

	if {$msg == "outp:"} {
		extraireContenu $chaine
		# Insertion du contenu du texte dans la console
    	.console insert end "$texteLu\n"
   		#Positionnement du curseur à la fin de la console d'affichage
    	.console see end
	} elseif {$msg == "coor:"} {
		extraireContenu $chaine
		UpdateInfosPCod .txt_compteurOrdinal $texteLu
	} elseif {$msg == "flag:"} {
		extraireContenu $chaine
		UpdateInfosPCod .txt_flag $texteLu
	} elseif {$msg == "riii:"} {
		extraireContenu $chaine
		UpdateInfosPCod .txt_lastInstr $texteLu
	} elseif {$msg == "linb:"} {
		extraireContenu $chaine
		.txt_pCode tag remove sel 0.0 999.999
		.txt_pCode tag add sel $texteLu.0 $texteLu.999
	} elseif {$msg == "stac:"} {
		extraireContenu $chaine
		#découpage de la chaine lue en sous chaines grâce au délimiteur $
		set chaineStack [split $texteLu "$"]
		
		#nettoyage de la liste
		.lst_pile_execution delete 0 end
	
		#variable d'alternance entre variable et valeur
		set lireVar "true"
		
		set varPile ""
		
		#Remplissage de la pile d'exécution avec les éléments de la chaine lue
		foreach elem $chaineStack {
			if {$lireVar=="true"} {
				set varPile $elem
				set lireVar "false"
			} elseif {$lireVar=="false"} {
				set varPile "$varPile = $elem"
				.lst_pile_execution insert 0 $varPile
				set lireVar "true"
			}
		}

		#gets $pipeFichierLecture texteLu
	} elseif {$msg == "writ:"} {
		extraireContenu $chaine
    	# Insertion du contenu du fichier
    	.console insert end "$texteLu"
    	puts "$texteLu\n"
    	#Positionnement du curseur à la fin de la console d'affichage
    	.console see end
	} elseif {$msg == "wril:"} {
		extraireContenu $chaine
    	# Insertion du contenu du fichier
    	.console insert end "$texteLu\n"
    	#Positionnement du curseur à la fin de la console d'affichage
    	.console see end
	} elseif {$msg == "inpu:"} {
		extraireContenu $chaine
		focus .console_saisi
		#desactiverToutSaufConsole
	} elseif {$msg == "acti:"} {
		reactiverTout
		return
	}
}

#Extraction de la chaine située après l'en-tete du message et remplacement des caractères inutiles
proc extraireContenu {chaine} {
	global texteLu

	set texteLu [regexp -inline -all -- {\:.*} $chaine]
	set texteLu [string map {: ""} $texteLu]
	set texteLu [string map {\{ ""} $texteLu]
	set texteLu [string map {\} ""} $texteLu]
}

#Mise à jour des champs textes délivrants des informations sur le PCod
proc UpdateInfosPCod {widget texte} {
	$widget configure -state normal
	$widget delete 1.0 end
	$widget insert end $texte
	$widget configure -state disabled
}

#Permet de désactiver l'ensemble des composants de l'interface
proc desactiverToutSaufConsole {} {
	.lst_pile_execution configure -state disabled
	.console configure -state disabled
	.txt_compteurOrdinal configure -state disabled
	.txt_flag configure -state disabled
	.txt_lastInstr configure -state disabled
	.txt_compilation configure -state disabled
	.txt_pCode configure -state disabled
	.frame_commandes_pCode.btn_pCode_quit configure -state disabled
	.frame_commandes_pCode.btn_pCode_suivant configure -state disabled
	.frame_commandes_pCode.btn_pCode_exec configure -state disabled
	.lst_lignes_Pascal configure -state disabled
	.lst_lignes_PCode configure -state disabled
	.btn_analyser configure -state disabled
	.btn_compilation configure -state disabled
}

proc desactiverTout {} {
	desactiverToutSaufConsole
	.console_saisi configure -state disabled
}

#Permet de désactiver l'ensemble des composants de l'interface
proc reactiverTout {} {
	reactiverToutSaufConsole
	.console_saisi configure -state normal
}

proc reactiverToutSaufConsole {} {
	.lst_pile_execution configure -state normal
	.console configure -state normal
	.txt_compteurOrdinal configure -state normal
	.txt_flag configure -state normal
	.txt_lastInstr configure -state normal
	.txt_compilation configure -state normal
	.txt_pCode configure -state normal
	.frame_commandes_pCode.btn_pCode_quit configure -state normal
	.frame_commandes_pCode.btn_pCode_suivant configure -state normal
	.frame_commandes_pCode.btn_pCode_exec configure -state normal
	.lst_lignes_Pascal configure -state normal
	.lst_lignes_PCode configure -state normal
	.btn_analyser configure -state normal
	.btn_compilation configure -state normal
}
